/**
 * 
 */
package photosalvage.entity;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import com.google.inject.Provider;
import com.google.inject.persist.Transactional;

/**
 * @author shumpei
 *
 */
public class BaseRepository<T, K> {
	private final Class<T> entityType;
	
	@SuppressWarnings("unused")
	private final Class<K> keyType;
	
	@Inject
	private Provider<EntityManager> entityManagerRef;
	
	public EntityManager getEntityManager() {
		return entityManagerRef.get();
	}
	
	@SuppressWarnings("unchecked")
	public BaseRepository() {
		ParameterizedType pType = null;
		Class<?> c = getClass();
		while (true) {
			Type type = c.getGenericSuperclass();
			if (type instanceof ParameterizedType) {
				pType = (ParameterizedType) type;
				break;
			}
			c = (Class<?>) type;
		}
		entityType = (Class<T>) pType.getActualTypeArguments()[0];
		keyType =  (Class<K>) pType.getActualTypeArguments()[1];
	}
	
	@Transactional
	public T find(K key) {
		return entityManagerRef.get().find(entityType, key);
	}
	
	public List<T> findAll() {
		CriteriaBuilder queryBuilder = entityManagerRef.get().getCriteriaBuilder();
		CriteriaQuery<T> q = queryBuilder.createQuery(entityType);
		q.from(entityType);
		return entityManagerRef.get().createQuery(q).getResultList();
	}
	@Transactional
	public void persist(T entity) {
		entityManagerRef.get().persist(entity);
	}
	@Transactional
	public void merge(T entity) {
		entityManagerRef.get().merge(entity);
	}
	@Transactional
	public void remove(K key) {
		entityManagerRef.get().remove(key);
	}
}
